package fi.jamk.ourcookingapp.backend.architecture;

import java.util.List;
import java.util.concurrent.ExecutionException;

import org.json.JSONException;

import android.content.res.Resources;

import fi.jamk.ourcookingapp.backend.MyTools;
import fi.jamk.ourcookingapp.backend.architecture.interfaces.ICommentManager;
import fi.jamk.ourcookingapp.backend.architecture.interfaces.IReceiptManager;
import fi.jamk.ourcookingapp.backend.architecture.interfaces.IUserManager;
import fi.jamk.ourcookingapp.backend.architecture.services.ReceiptServices;
import fi.jamk.ourcookingapp.backend.architecture.services.UserServices;
import fi.jamk.ourcookingapp.backend.exceptions.EmptyInputException;
import fi.jamk.ourcookingapp.backend.exceptions.EmptySearchException;
import fi.jamk.ourcookingapp.backend.exceptions.NoIngredientsException;
import fi.jamk.ourcookingapp.backend.exceptions.NoRatingException;
import fi.jamk.ourcookingapp.backend.exceptions.NoReceiptException;
import fi.jamk.ourcookingapp.backend.exceptions.NoResultException;
import fi.jamk.ourcookingapp.backend.exceptions.NoStepsException;
import fi.jamk.ourcookingapp.backend.exceptions.NoUserException;
import fi.jamk.ourcookingapp.backend.exceptions.WebServiceException;
import fi.jamk.ourcookingapp.backend.model.Comment;
import fi.jamk.ourcookingapp.backend.model.Ingredient;
import fi.jamk.ourcookingapp.backend.model.Rating;
import fi.jamk.ourcookingapp.backend.model.Receipt;
import fi.jamk.ourcookingapp.backend.model.Step;
import fi.jamk.ourcookingapp.backend.model.User;

public class OurCookingFacade {

	private ReceiptServices rServices;
	
	private UserServices uServices;
	
	private User currentUser;

	private Resources resources;
	
	public OurCookingFacade() {
		this.rServices = new ReceiptServices();
		this.uServices = new UserServices();
	}
	
	public void setResources(Resources resources) {
		this.resources = resources;
	}
	
	public Resources getResources(){
		return this.resources;
	}
	
	/**
	 * Returns the current user of the app
	 * @return User
	 */
	public User getCurrentUser(){
		return this.currentUser;
	}
	
	/**
	 * @see IReceiptManager
	 * @param receipt
	 * @param user
	 * @throws NoReceiptException
	 * @throws JSONException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 */
	public void addToFavourite(Receipt receipt, User user) throws NoReceiptException, JSONException, InterruptedException, ExecutionException{
		if(receipt == null){
			throw new NoReceiptException();
		}
		this.rServices.addToFavourite(receipt, user);
	}
	
	/**
	 * @see IReceiptManager
	 * @param receipt
	 * @return
	 * @throws NoReceiptException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 */
	public boolean deleteReceipt(Receipt receipt) throws NoReceiptException, InterruptedException, ExecutionException, JSONException {
		if(receipt == null){
			throw new NoReceiptException();
		}
		return this.rServices.deleteReceipt(receipt);
	}

	/**
	 * @see IReceiptManager
	 * @param receipt
	 * @return
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 * @throws NoIngredientsException 
	 * @throws NoStepsException 
	 */
	public Receipt updateReceipt(Receipt receipt, boolean clicks) throws InterruptedException, ExecutionException, JSONException, NoIngredientsException, NoStepsException {
		if(!clicks && receipt.getLstIngredient().isEmpty()){
			throw new NoIngredientsException();
		}
		if(!clicks && receipt.getLstStep().isEmpty()){
			throw new NoStepsException();
		}
		return this.rServices.updateReceipt(receipt, clicks);
	}

	/**
	 * @see IReceiptManager
	 * @param receipt
	 * @return
	 * @throws NoReceiptException
	 * @throws NoIngredientsException
	 * @throws NoStepsException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 */
	public Receipt createReceipt(Receipt receipt) throws NoReceiptException, NoIngredientsException, NoStepsException, InterruptedException, ExecutionException, JSONException {
		if(receipt == null){
			throw new NoReceiptException();
		}
		return this.rServices.createReceipt(receipt);
	}

	/**
	 * @see IReceiptManager
	 * @return
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 * @throws NoReceiptException 
	 */
	public List<Receipt> filter(boolean count) throws InterruptedException, ExecutionException, JSONException, NoReceiptException {
		return this.rServices.filter(count);
	}

	/**
	 * @see IReceiptManager
	 * @param key
	 * @param value
	 * @throws EmptySearchException
	 */
	public void setFilter(String key, Object value) throws EmptySearchException{
		if(MyTools.isEmpty(key)){
			throw new EmptySearchException("addFilter");
		}
		this.rServices.setFilter(key, value);
	}
	
	/**
	 * @see IReceiptManager
	 * @param key
	 * @param value
	 * @throws EmptySearchException
	 */
	public void setOption(String key, String value) throws EmptySearchException{
		if(MyTools.isEmpty(key) || MyTools.isEmpty(value)){
			throw new EmptySearchException("addOption");
		}
		this.rServices.setOption(key, value);
	}
	
	/**
	 * @see IReceiptManager
	 * @param receipt
	 * @param rating
	 * @return
	 * @throws NoReceiptException
	 * @throws NoRatingException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws NumberFormatException
	 * @throws JSONException
	 */
	public double rateReceipt(Receipt receipt, Rating rating) throws NoReceiptException, NoRatingException, InterruptedException, ExecutionException, NumberFormatException, JSONException {
		if(receipt == null){
			throw new NoReceiptException();
		}
		if(rating == null){
			throw new NoRatingException();
		}
		return this.rServices.rateReceipt(receipt, rating);
	}

	/**
	 * @see IReceiptManager
	 * @return
	 * @throws NoResultException
	 * @throws JSONException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 */
	public List<Ingredient> getAllIngredients() throws NoResultException, JSONException, InterruptedException, ExecutionException{
		return this.rServices.getAllIngredients();
	}
	
	/**
	 * @see IUserManager
	 * @param user
	 * @return
	 * @throws NoUserException
	 * @throws EmptyInputException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 * @throws WebServiceException
	 */
	public User createUser(User user) throws NoUserException, EmptyInputException, InterruptedException, ExecutionException, JSONException, WebServiceException {
		if(user == null){
			throw new NoUserException();
		}
		this.currentUser = this.uServices.createUser(user);
		return currentUser;
	}

	/**
	 * @see IUserManager
	 * @param user
	 * @param userToAdd
	 * @return
	 * @throws EmptyInputException
	 * @throws NoUserException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 */
	public boolean addToFriendList(User user, User userToAdd) throws EmptyInputException, NoUserException, InterruptedException, ExecutionException, JSONException {
		if(user == null || userToAdd == null){
			throw new NoUserException();
		}
		return this.uServices.addToFriendList(user, userToAdd);
	}

	/**
	 * @see IUserManager
	 * @param user
	 * @return
	 * @throws NoUserException
	 * @throws EmptyInputException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 * @throws WebServiceException
	 */
	public User login(User user) throws NoUserException, EmptyInputException, InterruptedException, ExecutionException, JSONException, WebServiceException {
		this.currentUser = user.getID() > 0 ? user : this.uServices.login(user);
		return this.currentUser;
	}

	/**
	 * @see ICommentManager
	 * @param comment
	 * @return
	 * @throws EmptyInputException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 */
	public boolean createComment(Comment comment) throws EmptyInputException, InterruptedException, ExecutionException, JSONException {
		if(MyTools.isEmpty(comment.getText())){
			throw new EmptyInputException("Comment: " + comment.getText());
		}
		return this.uServices.createComment(comment);
	}

	/**
	 * @see ICommentManager
	 * @param receipt
	 * @return
	 * @throws NoReceiptException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 */
	public List<Comment> commentsByReceipt(Receipt receipt) throws NoReceiptException, InterruptedException, ExecutionException, JSONException {
		if(receipt == null){
			throw new NoReceiptException();
		}
		return this.uServices.commentsByReceipt(receipt);
	}

	/**
	 * @see IReceiptManager
	 * @return
	 * @throws JSONException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 */
	public List<Receipt> getFavourites() throws JSONException, InterruptedException, ExecutionException {
		return this.rServices.getFavourites(currentUser);
	}

	/**
	 * @see IUserManager
	 * @return
	 * @throws InterruptedException
	 * @throws ExecutionException
	 * @throws JSONException
	 * @throws NoUserException 
	 */
	public List<User> friendList() throws InterruptedException, ExecutionException, JSONException, NoUserException {
		return this.uServices.friendList(currentUser);
	}

	/**
	 * @see IReceiptManager
	 * @param receipt
	 * @return
	 * @throws JSONException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 */
	public List<Ingredient> ingredientsByReceipt(Receipt receipt) throws JSONException, InterruptedException, ExecutionException {
		return this.rServices.ingredientsByReceipt(receipt);
	}

	/**
	 * @see IReceiptManager
	 * @param receipt
	 * @return
	 * @throws JSONException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 */
	public List<Step> stepsByReceipt(Receipt receipt) throws JSONException, InterruptedException, ExecutionException {
		return this.rServices.stepsByReceipt(receipt);
	}

	/**
	 * @see IReceiptManager
	 * @param receipt
	 * @param user
	 * @throws JSONException
	 * @throws InterruptedException
	 * @throws ExecutionException
	 */
	public void removeFromFavourite(Receipt receipt, User user) throws JSONException, InterruptedException, ExecutionException {
		this.rServices.removeFromFavourite(receipt, user);
	}

	
}
